package caom.wangs.java8.streamDemo;

import caom.wangs.java8.pojo.Person;
import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Demo3 {
    @Test
    public void test1() {
        Stream<String> stringSream = Stream.of("a1", "a2", "a3");
//        stringSream.filter(s -> {
//            System.out.println("-----");
//            return s.contains("a");
//        }).forEach(System.out::println);

        stringSream.filter(s -> s.contains("a")).forEach(System.out::println);

        long count = stringSream.count();
        System.out.println(count);
    }

    @Test
    public void test2() {
        Stream<String> stringSream = Stream.of("a1", "a2", "a3", "bb", "cc", "dd", "ee");
//        stringSream.filter(s -> s.contains("a")).limit(3).skip(1).forEach(System.out::println);
        Stream<String> limit = stringSream.limit(3);
        limit.forEach(System.out::println);
    }

    @Test
    public void test3() {
        Stream<String> stringStream = Stream.of("1", "3", "5", "4", "0");
        Stream<Integer> integerStream = stringStream.map(Integer::parseInt).sorted(((o1, o2) -> o2 - o1));
        integerStream.forEach(System.out::println);

        Stream<Person> personStream = Stream.of(
                new Person("wst", 22, 22.0),
                new Person("wt", 22, 22.0),
                new Person("wst", 22, 22.0));
        personStream.distinct().forEach(System.out::println);
    }

    /**
     * Java：
     * - reduce：需提供默认值（初始值）
     * Kotlin：
     * - fold：不需要默认值（初始值）
     * - reduce：需提供默认值（初始值）
     */
    @Test
    public void test01() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Integer integer = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(integer);

        List<Integer> lists = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Integer reduce = lists.stream().reduce(0, (x, y) -> {
            return x > y ? x : y;
        });
        System.out.println(reduce);
    }

    @Test
    public void test02() {
        Stream<Person> personStream = Stream.of(
                new Person("wst", 22, 22.0),
                new Person("wt", 221, 22.0),
                new Person("wst", 22, 22.0));
        Integer reduce = personStream
//                .map(person -> person.getAge())
                .map(Person::getAge)
//                .reduce(0, (x, y) -> x + y);
//                .reduce(0, Integer::sum);
//                .reduce(0, Integer::max);
                .reduce(0, Math::max);
        System.out.println(reduce);

        Integer reduce1 = Stream.of("a", "b", "a").map(ch -> "a".contains(ch) ? 1 : 0).reduce(0, Integer::sum);
        System.out.println(reduce1);
    }

    @Test
    public void test03() {

        Integer[] arr = {1, 2, 3, 4, 5, 6};
        Stream.of(arr).filter(i -> i > 0)
                .forEach(System.out::println);
        System.out.println("------------");

        IntStream intStream = Stream.of(arr).mapToInt(Integer::intValue);
        intStream.filter(i -> i > 3).forEach(System.out::println);
    }

    @Test
    public void test04() {
        Stream<String> a = Stream.of("a", "b", "c");
        Stream<String> d = Stream.of("d", "e", "f");
        Stream<String> concat = Stream.concat(a, d);
        concat.forEach(System.out::println);
    }

    @Test
    public void test05() {
        List<String> list1 = Arrays.asList("wst", "nmw", "swj", "张三丰");
        List<String> list2 = Arrays.asList("欧阳玉宝", "孙悟空", "swj", "王凡");

        Stream<String> limit = list1.stream().filter(s -> s.length() == 3).limit(3);

        Stream<String> concat = Stream.concat(list1.stream(), list2.stream());

//        Stream.concat(limit,concat).map(n-> new Person(n)).forEach(System.out::println);
        Stream.concat(limit, concat).map(Person::new).forEach(System.out::println);


    }

    @Test
    public void test06() {
        List<String> list = Stream.of("aa", "bb", "cc", "aa")
                .collect(Collectors.toList());

        System.out.println(list);

        Set<String> set = Stream.of("aa", "bb", "cc", "aa").collect(Collectors.toSet());
        System.out.println(set);

        ArrayList<String> arrayList = Stream.of("aa", "bb", "cc", "aa")
                .collect(Collectors.toCollection(ArrayList::new));
        System.out.println(arrayList);
    }

    @Test
    public void test07() {
        Object[] objects = Stream.of("aa", "bb", "cc", "aa")
                .toArray();

        System.out.println(Arrays.toString(objects));

        String[] strings = Stream.of("aa", "bb", "cc", "aa")
                .toArray(String[]::new);
        System.out.println(strings);

    }

    @Test
    public void test08() {
        Stream<Person> personStream = Stream.of(
                new Person("wst", 22, 22.0),
                new Person("wt", 221, 22.0),
                new Person("wst", 22, 22.0));
        Optional<Person> collect = personStream.collect(
                Collectors.maxBy((p1, p2) -> p1.getAge() - p2.getAge()));
        System.out.println(collect.get());

        Stream<Person> personStream1 = Stream.of(
                new Person("wst", 22, 22.0),
                new Person("wt", 221, 22.0),
                new Person("wst", 22, 22.0));
        Optional<Person> collect1 = personStream1.collect(
                Collectors.minBy((p1, p2) -> p1.getAge() - p2.getAge()));
        System.out.println(collect1.get());

        Integer collect2 = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .collect(
                        Collectors.summingInt(Person::getAge));
//        Collectors.summingInt(s -> s.getAge()));
        System.out.println(collect2);

        Double collect3 = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .collect(
                        Collectors.averagingDouble(Person::getAge));
//        Collectors.averagingDouble(s -> s.getAge()));
        System.out.println(collect3);

        Long collect4 = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .filter(p -> p.getAge() > 10)
                .collect(
                        Collectors.counting());
        System.out.println(collect4);
    }


    @Test
    public void test09() {
        Map<Integer, List<Person>> collect = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .collect(Collectors.groupingBy(Person::getAge));
        collect.forEach((k, v) -> System.out.println(k + ":" + v));

        Map<String, List<Person>> collect1 = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .collect(Collectors
                        .groupingBy(
                                p -> p.getAge() >= 18 ? "成年" : "未成年"));
        collect1.forEach((k, v) -> System.out.println(k + ":" + v));


    }

    @Test
    public void test10() {
        Map<Integer, Map<String, List<Person>>> collect = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .collect(Collectors.groupingBy(Person::getAge
                        ,
                        Collectors.groupingBy(Person::getName)));

        collect.forEach((k, v) -> System.out.println(k + ":" + v));

        collect.forEach((k, v) -> {
            System.out.println(k);
            v.forEach((k1, v1) -> {
                System.out.println(k1 + ":" + v1);
            });
        });


    }

    @Test
    public void test11() {
        Map<Boolean, List<Person>> collect = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .collect(Collectors.partitioningBy(p -> p.getAge() > 18));
        collect.forEach((k, v) -> System.out.println(k + ":" + v));

    }

    @Test
    public void test12() {
        String collect = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .map(Person::getName)
                .collect(Collectors.joining());
        System.out.println(collect);

        String collect1 = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .map(Person::getName)
                .collect(Collectors.joining("_"));
        System.out.println(collect1);

        String collect2 = Stream.of(
                        new Person("wst", 22, 22.0),
                        new Person("wt", 221, 22.0),
                        new Person("wst", 22, 22.0))
                .map(Person::getName)
                .collect(Collectors.joining("_", "###", "$$$"));
        System.out.println(collect2);
    }
}